﻿#region copyright
//                Copyright Andrew Rafas 2012.
// Distributed under the Eclipse Public License, Version 1.0.
//           (See accompanying file LICENSE.txt or 
//     copy at http://www.eclipse.org/legal/epl-v10.html)
#endregion
using System;
using System.Diagnostics.Contracts;
using System.Collections.Generic;

namespace CSFP
{
    public struct FilterSeq<T, S> : ISeq<T, FilterSeq<T, S>>, IEnumerable<T>
        where S : struct, ISeq<T, S>
    {
        readonly Predicate<T> _pred;
        readonly S _current;

        public FilterSeq(Predicate<T> pred, S seq)
        {
            Contract.Requires<ArgumentNullException>(pred != null);

            _pred = pred;
            _current = seq;
            // skip filtered out items
            while (_current.IsValid && !_pred(_current.First))
                _current = _current.Next;
        }

        public bool IsValid { get { return _current.IsValid; } }
        public T First { get { return _current.First; } }
        public FilterSeq<T, S> Next { get { return new FilterSeq<T, S>(_pred, _current.Next); } }

        public IEnumerator<T> GetEnumerator() { return new SeqEnumerator<T, FilterSeq<T, S>>(this); }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((IEnumerable<T>)this).GetEnumerator(); }
    }

    public static partial class Functions
    {
        public static FilterSeq<T, S> Filter<T, S>(this S seq, Predicate<T> pred)
            where S : struct, ISeq<T, S>
        {
            Contract.Requires<ArgumentNullException>(pred != null);

            return new FilterSeq<T, S>(pred, seq);
        }
    }
}
